﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.ESG.Entities;
using Sustainalytics.Utils;
using MongoDB.Driver;
using System.Threading.Tasks;

namespace Sustainalytics.ESGRatings.BusinessLogic.ESGOnlineReport
{
    public class OnlineReportAnalystBusinessLogicUnit 
    {

        private readonly IMongoCollection<Analyst> _analystRepositoryCollection;

        private readonly IMongoCollection<CorporateData> _corporateDataRepositoryCollection;

        private readonly IMongoCollection<RPCompanyProfile> _rpCompanyProfileRepositoryCollection;

        public OnlineReportAnalystBusinessLogicUnit(IMongoCollection<Analyst> analystRepositoryCollection, 
                                                    IMongoCollection<CorporateData> corporateDataRepositoryCollection, 
                                                    IMongoCollection<RPCompanyProfile> rpCompanyProfileRepositoryCollection)
        {
            _analystRepositoryCollection = analystRepositoryCollection;
            _corporateDataRepositoryCollection = corporateDataRepositoryCollection;
            _rpCompanyProfileRepositoryCollection = rpCompanyProfileRepositoryCollection;
        }

        /// <exception cref="ESGReasearchNotInUniversesException">corporatedata has no matching Universe</exception>
        /// <exception cref="ESGReasearchNotFoundException"> Not in database. </exception>
        public async Task<IList<Analyst>> GetByCompanyId(Guid companyId, IEnumerable<int> universeIds)
        {
            var corporate = await _corporateDataRepositoryCollection.Find(x=>x.Id==companyId).Project(x=>x.UniverseIds).FirstOrDefaultAsync();
            if (corporate == null || !corporate.Intersect(universeIds).Any())
                throw new ESGReasearchNotInUniversesException();

            var analystId = await _rpCompanyProfileRepositoryCollection.Find(profile => profile.Id == companyId).Project(X=>X.AnalystId).FirstOrDefaultAsync();

            if (analystId == Guid.Empty)
                throw new ESGReasearchNotFoundException();

            var analystsList = await _analystRepositoryCollection.Find(a => a.Id == analystId).ToListAsync();

            if (analystsList.IsNullOrEmpty())
                throw new ESGReasearchNotFoundException();

            return analystsList;
        }

        /// <exception cref="ESGReasearchNotInUniversesException">corporatedata has no matching Universe</exception>
        /// <exception cref="ESGReasearchNotFoundException"> Not in database. </exception>
        public async Task<Analyst> GetSingleByCompanyId(Guid companyId, IEnumerable<int> universeIds)
        {

            var corporateData = await _corporateDataRepositoryCollection.Find(x => x.Id == companyId).Project<CorporateData>(
                Builders<CorporateData>.Projection
                    .Include(x => x.ComprehensiveEsgResearchState)
                    .Include(x => x.CoreEsgResearchState)).FirstOrDefaultAsync();

            if (corporateData == null)
                throw new ESGReasearchNotFoundException();

            if (corporateData.CoreEsgResearchState.ResearchState == BusinessResearchProductStates.Entities.ResearchState.ResearchState.ResearchAvailable)
                return null;

            var analystId = await _rpCompanyProfileRepositoryCollection.Find(profile => profile.Id == companyId).Project(X => X.AnalystId).FirstOrDefaultAsync();

            if (analystId == Guid.Empty)
                throw new ESGReasearchNotFoundException();

            var analyst = await _analystRepositoryCollection.Find(a => a.Id == analystId).FirstOrDefaultAsync();

            if (analyst == null)
                throw new ESGReasearchNotFoundException();


            return analyst;
        }


        /// <exception cref="ESGReasearchNotInUniversesException">corporatedata has no matching Universe</exception>
        /// <exception cref="ESGReasearchNotFoundException"> Not in database. </exception>
        public async Task<byte[]> GetImage(Guid companyId)
        {
            var analystId = await _rpCompanyProfileRepositoryCollection.Find(profile => profile.Id == companyId).Project(X => X.AnalystId).FirstOrDefaultAsync();

            if (analystId == Guid.Empty)
                throw new ESGReasearchNotFoundException();


            var analyst = await _analystRepositoryCollection.Find(a => a.Id == analystId).FirstOrDefaultAsync();

            if (analyst == null)
                throw new ESGReasearchNotFoundException();


            return analyst.Picture;
        }


        /// <exception cref="ESGReasearchNotInUniversesException">corporatedata has no matching Universe</exception>
        /// <exception cref="ESGReasearchNotFoundException"> Not in database. </exception>
        public async Task<string> GetAnalystCommentary(Guid companyId, IEnumerable<int> universeIds)
        {
            var corporateData = await _corporateDataRepositoryCollection.Find(x => x.Id == companyId).Project(x => x.UniverseIds).FirstOrDefaultAsync();

            if (corporateData == null || !corporateData.Intersect(universeIds).Any())
                throw new ESGReasearchNotInUniversesException();

            var AnalystCommentary = await _rpCompanyProfileRepositoryCollection.Find(profile => profile.Id == companyId).Project(x=>x.AnalystCommentary).FirstOrDefaultAsync();

            if (string.IsNullOrWhiteSpace(AnalystCommentary))
                throw new ESGReasearchNotFoundException();

            return AnalystCommentary;
        }
    }
}